/**
 * @file snakegamemanager.h
 * @brief Snake游戏管理器类头文件
 *
 * SnakeGameManager是Snake游戏的核心管理器，负责：
 * - 整合WebSocket通信和API调用
 * - 管理游戏状态和生命周期
 * - 处理用户输入和游戏控制
 * - 协调各个游戏组件的交互
 * - 提供统一的游戏接口
 */

#ifndef SNAKEGAMEMANAGER_H
#define SNAKEGAMEMANAGER_H

#include <QObject>              // Qt对象基类
#include <QTimer>               // 定时器
#include <QJsonObject>          // JSON对象处理
#include <QDateTime>            // 时间处理
#include "snakegamestate.h"
#include "websocketclient.h"
#include "snakeapiclient.h"

/**
 * @class SnakeGameManager
 * @brief Snake游戏管理器类
 *
 * 作为Snake游戏的核心控制器，整合所有游戏相关的功能模块，
 * 提供统一的游戏管理接口。负责游戏的完整生命周期管理。
 */
class SnakeGameManager : public QObject
{
    Q_OBJECT  // 启用Qt元对象系统

public:
    /**
     * @enum ConnectionStatus
     * @brief 连接状态枚举
     */
    enum ConnectionStatus {
        Disconnected = 0,       ///< 未连接
        Connecting,             ///< 连接中
        Connected,              ///< 已连接
        Authenticated,          ///< 已认证
        InGame,                 ///< 游戏中
        Error                   ///< 错误状态
    };
    Q_ENUM(ConnectionStatus)

    /**
     * @struct GameConfig
     * @brief 游戏配置结构
     */
    struct GameConfig {
        QString roomName;               ///< 房间名称
        int maxPlayers = 4;             ///< 最大玩家数
        int gameMode = 1;               ///< 游戏模式
        int mapWidth = 40;              ///< 地图宽度
        int mapHeight = 30;             ///< 地图高度
        int gameSpeedMs = 100;          ///< 游戏速度（毫秒）
        bool enableWalls = true;        ///< 启用墙壁
        bool enableSpecialFoods = false; ///< 启用特殊食物
        int maxFoodCount = 10;          ///< 最大食物数量
    };

    /**
     * @struct WebSocketConfig
     * @brief WebSocket连接配置结构（新业务流程）
     */
    struct WebSocketConfig {
        QString url;                    ///< WebSocket服务器URL
        QString gameToken;              ///< WebSocket连接认证令牌（access_token）
        QString sessionToken;           ///< WebSocket消息认证令牌（session_token）
        QString playerId;               ///< 玩家ID
        QString playerName;             ///< 玩家名称
        QString clientType = "qt6";     ///< 客户端类型
        QString protocolVersion = "1.0"; ///< 协议版本
        int heartbeatInterval = 30000;  ///< 心跳间隔（毫秒）
        bool autoReconnect = true;      ///< 自动重连
        int maxReconnectAttempts = 5;   ///< 最大重连次数
    };

    explicit SnakeGameManager(QObject *parent = nullptr);
    ~SnakeGameManager();

    // === 初始化和配置 ===
    /**
     * @brief 初始化游戏管理器
     * @param apiGatewayUrl API网关URL
     * @param accessToken 访问令牌
     */
    void initialize(const QString &apiGatewayUrl, const QString &accessToken);

    /**
     * @brief 设置当前玩家信息
     * @param playerId 玩家ID
     * @param playerName 玩家名称
     */
    void setPlayerInfo(const QString &playerId, const QString &playerName);

    // === 连接管理 ===
    /**
     * @brief 连接到游戏服务器
     * @param preferredServerId 首选服务器ID（可选）
     * @param region 首选地区（可选）
     */
    void connectToGameServer(const QString &preferredServerId = QString(),
                            const QString &region = QString());

    /**
     * @brief 断开游戏服务器连接
     */
    void disconnectFromGameServer();

    /**
     * @brief 直接连接WebSocket服务器（新业务流程）
     * @param config WebSocket连接配置
     * @return 是否成功开始连接
     */
    bool connectToWebSocket(const WebSocketConfig &config);

    /**
     * @brief 获取连接状态
     * @return 当前连接状态
     */
    ConnectionStatus getConnectionStatus() const { return m_connectionStatus; }

    /**
     * @brief 是否已连接到游戏
     * @return true表示已连接并可以游戏
     */
    bool isConnectedToGame() const { return m_connectionStatus == InGame; }

    /**
     * @brief 获取WebSocket客户端
     * @return WebSocket客户端指针
     */
    WebSocketClient* getWebSocketClient() const { return m_webSocketClient; }

    // === 房间管理 ===
    /**
     * @brief 获取房间列表
     * @param status 房间状态筛选（可选）
     * @param gameMode 游戏模式筛选（可选）
     */
    void getRoomList(const QString &status = QString(), int gameMode = -1);

    /**
     * @brief 创建房间
     * @param config 房间配置
     */
    void createRoom(const GameConfig &config);

    /**
     * @brief 加入房间
     * @param roomId 房间ID
     */
    void joinRoom(const QString &roomId);

    /**
     * @brief 离开房间
     */
    void leaveRoom();

    /**
     * @brief 获取当前房间ID
     * @return 当前房间ID
     */
    QString getCurrentRoomId() const;

    // === 游戏控制 ===
    /**
     * @brief 改变移动方向
     * @param direction 新方向（0=上，1=右，2=下，3=左）
     */
    void changeDirection(int direction);

    /**
     * @brief 改变移动方向（使用枚举）
     * @param direction 新方向
     */
    void changeDirection(Direction direction);

    /**
     * @brief 发送聊天消息
     * @param message 聊天内容
     */
    void sendChatMessage(const QString &message);

    // === 游戏状态访问 ===
    /**
     * @brief 获取游戏状态管理器
     * @return 游戏状态管理器指针
     */
    SnakeGameState* getGameState() const { return m_gameState; }

    /**
     * @brief 获取当前玩家的蛇数据
     * @return 当前玩家蛇数据指针，如果不存在返回nullptr
     */
    const SnakeData* getCurrentPlayerSnake() const;

    /**
     * @brief 获取游戏统计信息
     * @return 统计信息JSON对象
     */
    QJsonObject getGameStats() const;

    // === 数据查询 ===
    /**
     * @brief 获取玩家统计信息
     */
    void getPlayerStats();

    /**
     * @brief 获取排行榜
     * @param type 排行榜类型
     */
    void getLeaderboard(const QString &type = "all_time");

    /**
     * @brief 获取游戏历史记录
     */
    void getGameHistory();

    // === 配置管理 ===
    /**
     * @brief 获取游戏配置
     */
    void getGameConfig();

    /**
     * @brief 更新玩家配置
     * @param config 玩家配置
     */
    void updatePlayerConfig(const QJsonObject &config);

    // === WebSocket消息发送 ===
    /**
     * @brief 发送WebSocket消息
     * @param message JSON消息对象
     * @return 是否发送成功
     */
    bool sendMessage(const QJsonObject &message);

signals:
    // === 连接状态信号 ===
    /**
     * @brief 连接状态改变信号
     * @param status 新的连接状态
     */
    void connectionStatusChanged(ConnectionStatus status);

    /**
     * @brief 连接成功信号
     */
    void connected();

    /**
     * @brief 断开连接信号
     * @param reason 断开原因
     */
    void disconnected(const QString &reason);

    /**
     * @brief 连接错误信号
     * @param error 错误信息
     */
    void connectionError(const QString &error);

    /**
     * @brief WebSocket认证成功信号
     * @param authResult 认证结果
     */
    void authenticated(const QJsonObject &authResult);

    /**
     * @brief WebSocket认证失败信号
     * @param error 错误信息
     */
    void authenticationFailed(const QString &error);

    // === 游戏服务器信号 ===
    /**
     * @brief 游戏服务器列表获取成功信号
     * @param servers 服务器列表
     */
    void gameServersReceived(const QList<SnakeApiClient::GameServerInfo> &servers);

    /**
     * @brief 游戏登录成功信号
     * @param loginResult 登录结果
     */
    void gameLoginSucceeded(const SnakeApiClient::GameLoginResult &loginResult);

    /**
     * @brief 游戏登录失败信号
     * @param error 错误信息
     */
    void gameLoginFailed(const QString &error);

    // === 房间管理信号 ===
    /**
     * @brief 房间列表获取成功信号
     * @param rooms 房间列表
     */
    void roomListReceived(const QList<SnakeApiClient::RoomInfo> &rooms);

    /**
     * @brief 房间创建成功信号
     * @param roomId 房间ID
     */
    void roomCreated(const QString &roomId);

    /**
     * @brief 加入房间成功信号
     * @param roomId 房间ID
     */
    void roomJoined(const QString &roomId);

    /**
     * @brief 离开房间信号
     */
    void roomLeft();

    // === 游戏状态信号 ===
    /**
     * @brief 游戏状态更新信号
     * @param gameState 游戏状态数据
     */
    void gameStateUpdated(const QJsonObject &gameState);

    /**
     * @brief 游戏开始信号
     * @param gameData 游戏开始数据
     */
    void gameStarted(const QJsonObject &gameData);

    /**
     * @brief 游戏结束信号
     * @param endData 游戏结束数据
     */
    void gameEnded(const QJsonObject &endData);

    /**
     * @brief 玩家加入信号
     * @param playerId 玩家ID
     * @param playerName 玩家名称
     */
    void playerJoined(const QString &playerId, const QString &playerName);

    /**
     * @brief 玩家离开信号
     * @param playerId 玩家ID
     */
    void playerLeft(const QString &playerId);

    /**
     * @brief 聊天消息信号
     * @param senderId 发送者ID
     * @param senderName 发送者名称
     * @param message 消息内容
     */
    void chatMessageReceived(const QString &senderId, const QString &senderName, const QString &message);

    // === 数据查询信号 ===
    /**
     * @brief 玩家统计信息获取成功信号
     * @param stats 玩家统计信息
     */
    void playerStatsReceived(const SnakeApiClient::PlayerStats &stats);

    /**
     * @brief 排行榜获取成功信号
     * @param leaderboard 排行榜数据
     * @param type 排行榜类型
     */
    void leaderboardReceived(const QJsonArray &leaderboard, const QString &type);

    /**
     * @brief 游戏历史记录获取成功信号
     * @param history 历史记录数据
     */
    void gameHistoryReceived(const QJsonArray &history);

    /**
     * @brief 游戏配置获取成功信号
     * @param config 游戏配置
     */
    void gameConfigReceived(const QJsonObject &config);

private slots:
    // === WebSocket事件处理 ===
    void onWebSocketConnected();
    void onWebSocketDisconnected(const QString &reason);
    void onWebSocketError(const QString &error);
    void onWebSocketGameError(const QString &errorCode, const QString &errorMessage);
    void onWebSocketAuthenticated(const QJsonObject &playerInfo);
    void onWebSocketAuthenticationFailed(const QString &error);
    void onWebSocketGameStateUpdated(const QJsonObject &gameState);
    void onWebSocketPlayerJoined(const QString &playerId, const QString &playerName);
    void onWebSocketPlayerLeft(const QString &playerId);
    void onWebSocketRoomCreated(const QString &roomId, const QJsonObject &roomInfo);
    void onWebSocketRoomJoined(const QString &roomId);
    void onWebSocketChatMessageReceived(const QString &senderId, const QString &senderName, const QString &message);
    void onWebSocketGameStarted(const QJsonObject &gameData);
    void onWebSocketGameEnded(const QJsonObject &results);

    // === API客户端事件处理 ===
    void onApiGameServersReceived(const QList<SnakeApiClient::GameServerInfo> &servers, const QString &recommendedServerId);
    void onApiGameLoginSucceeded(const SnakeApiClient::GameLoginResult &loginResult);
    void onApiGameLoginFailed(const QString &error);
    void onApiRoomListReceived(const QList<SnakeApiClient::RoomInfo> &rooms, int totalCount);
    void onApiPlayerStatsReceived(const SnakeApiClient::PlayerStats &stats);
    void onApiLeaderboardReceived(const QJsonArray &leaderboard, const QString &type);
    void onApiGameHistoryReceived(const QJsonArray &history);
    void onApiGameConfigReceived(const QJsonObject &config);
    void onApiError(const QString &endpoint, const QString &error);

private:
    // === 核心组件 ===
    SnakeGameState *m_gameState;        ///< 游戏状态管理器
    WebSocketClient *m_webSocketClient; ///< WebSocket客户端
    SnakeApiClient *m_apiClient;        ///< Snake API客户端

    // === 状态管理 ===
    ConnectionStatus m_connectionStatus; ///< 连接状态
    QString m_currentPlayerId;          ///< 当前玩家ID
    QString m_currentPlayerName;        ///< 当前玩家名称
    QString m_currentGameToken;         ///< 当前游戏令牌
    QString m_currentSessionId;         ///< 当前会话ID

    // === 服务器信息 ===
    QList<SnakeApiClient::GameServerInfo> m_availableServers; ///< 可用服务器列表
    SnakeApiClient::GameServerInfo m_currentServer; ///< 当前连接的服务器
    QString m_recommendedServerId;      ///< 推荐服务器ID

    // === 统计信息 ===
    qint64 m_connectTime;               ///< 连接时间
    int m_reconnectAttempts;            ///< 重连尝试次数

    // === 私有方法 ===
    void setConnectionStatus(ConnectionStatus status);
    void performGameLogin(const QString &preferredServerId, const QString &region);
    void connectWebSocket(const SnakeApiClient::GameLoginResult &loginResult);
    void resetState();
    void updateGameStats();
};

#endif // SNAKEGAMEMANAGER_H
